home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 5
/
Apprentice-Release5.iso
/
Source Code
/
C++
/
Frameworks
/
Sprocket Framework DR2
/
Sprocket Framework
/
Window.cp
< prev
Wrap
Text File
|
1996-06-15
|
24KB
|
999 lines
/*
File: Window.cp
Project: Sprocket Framework 1.1 (DR2), released 6/15/96
Contains: Base class which support all aspects of an on-screen window
To Do: Make sure invisible windows can be created & managed
Fix activate bugs when showing and hiding windows
Window positioning methods (getters and setters)
Changes to support AEObject model
Sprocket Major Contributors:
----------------------------
Dave Falkenburg, producer of Sprocket 1.0
Bill Hayden, producer of Sprocket 1.1
Steve Sisak, producer of the upcoming Sprocket 2.0
Pete Alexander Steve Falkenburg Randy Thelen
Eric Berdahl Nitin Ganatra Chris K. Thomas
Marshall Clow Dave Hershey Leonard Rosenthal
Tim Craycroft Dave Mark Dean Yu
David denBoer Gary Powell
Cameron Esfahani Jon Summers Apple Computer, Inc.
Comments, Additions, or Corrections:
------------------------------------
Bill Hayden, Nikol Software <nikol@codewell.com>
*/
#include "Sprocket.h"
#include "Window.h"
RgnHandle TWindow::fgScratchRgn = nil;
short TWindow::fgNumWindows = 0;
const short kFloatingWindowKind = 1000;
const short kNormalWindowKind = 1001;
const WindowRef kNoFloatingWindows = (WindowRef) -1;
const short kScreenEdgeSlop = 4;
const short kSpaceForFinderIcons = 64;
const short kMinimumTitleBarHeight = 21;
const short kMinimumWindowSize = 32;
static void HiliteShowHideFloatingWindows(Boolean hiliting,Boolean hiding);
static void FindScreenRectWithLargestPartOfWindow(WindowRef aWindow,Rect *theBestScreenRect, GDHandle * theBestDevice);
static pascal void CalculateWindowAreaOnDevice(short depth,short deviceFlags,GDHandle targetDevice,long userData);
struct CalcWindowAreaDeviceLoopUserData
{
GDHandle fScreenWithLargestPartOfWindow;
long fLargestArea;
Rect fWindowBounds;
};
TWindow::TWindow()
{
fIsDialogWindow = false;
if (fgScratchRgn == nil)
fgScratchRgn = NewRgn();
fgNumWindows++;
}
TWindow::~TWindow()
{
if ((--fgNumWindows <= 0) && (fgScratchRgn != nil))
{
DisposeRgn(fgScratchRgn);
fgScratchRgn = nil;
}
}
void TWindow::CreateWindow(WindowType typeOfWindowToCreate /* = kNormalWindow */)
{
WindowRef behindWindow, oldFrontMostWindow;
if (typeOfWindowToCreate == kModalWindow)
{
behindWindow = (WindowRef) -1;
oldFrontMostWindow = FrontWindow();
fWindowType = kModalWindow;
}
else if (typeOfWindowToCreate == kFloatingWindow)
{
behindWindow = (WindowRef) -1;
oldFrontMostWindow = FrontWindow();
fWindowType = kFloatingWindow;
}
else if (typeOfWindowToCreate == kNormalWindow)
{
behindWindow = LastFloatingWindow();
fWindowType = kNormalWindow;
if (behindWindow == kNoFloatingWindows)
oldFrontMostWindow = FrontNonFloatingWindow(); // •••
else
oldFrontMostWindow = GetNextWindow ( behindWindow );
}
fWindow = this->MakeNewWindow(behindWindow);
fIsVisible = IsWindowVisible ( fWindow );
if (fWindow)
{
SetWRefCon(fWindow,(long) this);
if (typeOfWindowToCreate == kModalWindow)
{
SetWindowKind ( fWindow, kNormalWindowKind );
HiliteAndActivateWindow(fWindow,true);
HiliteWindowsForModalDialog(false);
ShowWindow(fWindow);
HiliteAndActivateWindow(fWindow,true);
}
else if (typeOfWindowToCreate == kFloatingWindow)
{
SetWindowKind ( fWindow, kFloatingWindowKind );
// make sure the other window stays hilited
if (oldFrontMostWindow)
HiliteAndActivateWindow(oldFrontMostWindow,true);
}
else if (typeOfWindowToCreate == kNormalWindow)
{
SetWindowKind ( fWindow, kNormalWindowKind );
// unhighlight the old front window
if (oldFrontMostWindow)
HiliteAndActivateWindow(oldFrontMostWindow,false);
// hilite the new window…
HiliteAndActivateWindow(fWindow,true);
}
}
}
void
TWindow::AdjustCursor(EventRecord * /* anEvent */)
{
}
void
TWindow::Idle(EventRecord * /* anEvent */)
{
}
void
TWindow::Activate(Boolean /* activating */)
{
}
void
TWindow::Draw(void)
{
}
void
TWindow::Click(EventRecord * /* anEvent */)
{
this->Select();
}
void
TWindow::KeyDown(EventRecord * /* anEvent */)
{
}
Boolean TWindow::Select(void)
{
WindowRef currentFrontWindow;
if (fWindowType == kNormalWindow)
currentFrontWindow = FrontNonFloatingWindow();
else
currentFrontWindow = FrontWindow();
if (currentFrontWindow != fWindow)
{
TWindow* front = GetWindowObject(currentFrontWindow);
if (front->fWindowType == kModalWindow)
{
SysBeep(1);
return false; // window is not a legal destination for clicks
}
else if (fWindowType == kFloatingWindow)
BringToFront( fWindow );
else
{
WindowRef lastFloater = LastFloatingWindow();
// Deactivate the window currently in front.
HiliteAndActivateWindow(currentFrontWindow, false);
if (lastFloater == kNoFloatingWindows)
{
// If there are no floating windows,
// just call SelectWindow like the good ol’ days
SelectWindow(fWindow);
}
else
{
// Bring it behind the last floating window and activate it.
// Note that Inside Mac 1 states that you need to call PaintOne() and CalcVis() on a
// window if you are using SendBehind() to bring it closer to the front. With System 7,
// this is no longer necessary.
SendBehind( fWindow, lastFloater);
}
// Hilite the new front window
HiliteAndActivateWindow(fWindow,true);
}
}
return true; // window is a legal destination for clicks
}
void TWindow::Drag(Point startPoint)
{
GrafPtr savePort;
KeyMap theKeyMap;
Boolean commandKeyDown = false;
long dragResult;
WindowRef currentFrontWindow;
if (fWindowType == kNormalWindow)
currentFrontWindow = FrontNonFloatingWindow();
else
currentFrontWindow = FrontWindow();
if (currentFrontWindow != fWindow)
{
TWindow* front = GetWindowObject(currentFrontWindow);
if (front->fWindowType == kModalWindow)
{
SysBeep(1);
return; // window is not a legal drag
}
}
if (WaitMouseUp()) // de-bounce?
{
// Set up the Window Manager port.
GetPort(&savePort);
SetPort(gWindowManagerPort);
SetClip(GetGrayRgn());
// Check to see if the command key is down.
GetKeys(theKeyMap);
commandKeyDown = ((theKeyMap[1] & 0x8000) != 0);
if (commandKeyDown)
{
// We’re not going to change window ordering,
// so make sure that we don’t drag in front of
// other windows which may be in front of ours.
ClipAbove(fWindow);
}
else if (fWindowType != kFloatingWindow)
{
// We’re dragging a normal window, so make sure
// that we don’t drag in front of any floating
// windows.
ClipAbove(FrontNonFloatingWindow());
}
// Drag an outline of the window around the desktop.
// NOTE: DragGrayRgn destroys the region passed in, so make a copy
GetWindowStructureRgn(fWindow, fgScratchRgn);
dragResult = DragGrayRgn(fgScratchRgn, startPoint, &gDeskRectangle, &gDeskRectangle, noConstraint, nil);
SetPort(savePort); // Get back to old port
if ((dragResult != 0) && (dragResult != 0x80008000))
{
this->Nudge((short) (dragResult & 0xFFFF),(short) (dragResult >> 16));
}
}
if (!commandKeyDown)
Select();
}
void TWindow::Nudge(short horizontalDistance, short verticalDistance)
{
short newHorizontalPosition, newVerticalPosition;
RgnHandle tempRgn = NewRgn ();
GetWindowContentRgn ( fWindow, tempRgn );
newHorizontalPosition = (short) (**tempRgn).rgnBBox.left + horizontalDistance;
newVerticalPosition = (short) (**tempRgn).rgnBBox.top + verticalDistance;
DisposeRgn ( tempRgn );
::MoveWindow(fWindow, newHorizontalPosition, newVerticalPosition, false);
}
void TWindow::Grow(Point startPoint)
{
GrafPtr oldPort;
long newSize;
Rect oldWindowRect,resizeLimits;
GetPort(&oldPort);
GetWindowSizeLimits(&resizeLimits);
newSize = GrowWindow(fWindow,startPoint, &resizeLimits);
if (newSize)
{
oldWindowRect = GetWindowPort ( fWindow )->portRect;
SizeWindow ( fWindow, (short) newSize, (short) (newSize >> 16), true );
SetPortWindowPort ( fWindow );
resizeLimits = GetWindowPort ( fWindow )->portRect;
this->AdjustForNewWindowSize(&oldWindowRect, &resizeLimits);
}
SetPort(oldPort);
}
void TWindow::Zoom(short zoomState)
{
GrafPtr oldPort;
FontInfo systemFontInfo;
short titleBarHeight;
Rect bestScreenRect,perfectWindowRect,scratchRect;
short amountOffscreen;
// WindowPeek windowAsWindowPeek = (WindowPeek) fWindow;
GDHandle bestDevice;
GetPort(&oldPort);
// Figure out the height of the title bar so we can properly position
// a window. The algorithm is stolen from the System 7.x 'WDEF' (0)
//
// This probably isn’t the best thing to do: A better way might be
// to diff the structure and content region rectangles?
SetPort(gWindowManagerPort);
GetFontInfo(&systemFontInfo);
titleBarHeight = (short) (systemFontInfo.ascent + systemFontInfo.descent + 4);
if ((titleBarHeight % 2) == 1)
titleBarHeight--;
if (titleBarHeight < kMinimumTitleBarHeight)
titleBarHeight = kMinimumTitleBarHeight;
// Only do the voodoo magic if we are really “zooming” the window.
if (zoomState == inZoomOut)
{
FindScreenRectWithLargestPartOfWindow(fWindow,&bestScreenRect,&bestDevice);
bestScreenRect.top += titleBarHeight;
this->GetPerfectWindowSize(&perfectWindowRect);
OffsetRect(&perfectWindowRect,-perfectWindowRect.left,-perfectWindowRect.top);
// Take the zero-pinned perfect window size and move it to
// the top left of the window’s content region.
RgnHandle tempRgn = NewRgn ();
GetWindowContentRgn ( fWindow, tempRgn );
OffsetRect ( &perfectWindowRect,
(**tempRgn).rgnBBox.left, (**tempRgn).rgnBBox.top );
DisposeRgn ( tempRgn );
// Does perfectWindowRect fit completely on the best screen?
SectRect(&perfectWindowRect, &bestScreenRect, &scratchRect);
if (!EqualRect(&perfectWindowRect, &scratchRect))
{
// SectRect sez perfectWindowRect doesn’t completely fit
// on the screen, so bump the window so that more of it fits.
// Make sure that the left edge of perfectWindowRect is forced
// onto the best screen. This is in case we are bumping
// the window to the right.
amountOffscreen = bestScreenRect.left - perfectWindowRect.left;
if (amountOffscreen > 0)
{
perfectWindowRect.left += amountOffscreen;
perfectWindowRect.right += amountOffscreen;
}
// Make sure that the left edge of perfectWindowRect is forced
// onto the best screen. This is in case we are bumping
// the window downward to a new screen.
amountOffscreen = bestScreenRect.top - perfectWindowRect.top;
if (amountOffscreen > 0)
{
perfectWindowRect.top += amountOffscreen;
perfectWindowRect.bottom += amountOffscreen;
}
// If right edge of window falls off the screen,
// Move window to the left until the right edge IS on the screen
// OR the left edge is at bestScreenRect.left
amountOffscreen = perfectWindowRect.right - bestScreenRect.right;
if (amountOffscreen > 0)
{
// Are we going to push the left edge offscreen? If so, change the
// offset so we move the window all the way over to the left.
if ((perfectWindowRect.left - amountOffscreen) < bestScreenRect.left)
amountOffscreen = perfectWindowRect.left - bestScreenRect.left;
perfectWindowRect.left -= amountOffscreen;
perfectWindowRect.right -= amountOffscreen;
}
// If bottom edge of window falls off the screen,
// Move window to up until the bottom edge IS on the screen
// OR the top edge is at bestScreenRect.top
amountOffscreen = perfectWindowRect.bottom - bestScreenRect.bottom;
if (amountOffscreen > 0)
{
// Are we going to push the top edge offscreen? If so, change the
// offset so we move the window just to the top.
if ((perfectWindowRect.top - amountOffscreen) < bestScreenRect.top)
amountOffscreen = perfectWindowRect.top - bestScreenRect.top;
perfectWindowRect.top -= amountOffscreen;
perfectWindowRect.bottom -= amountOffscreen;
}
SectRect(&perfectWindowRect, &bestScreenRect, &scratchRect);
if (!EqualRect(&perfectWindowRect, &scratchRect))
{
// The edges of the window still fall offscreen,
// so make the window smaller until it fits.
if (perfectWindowRect.bottom > bestScreenRect.bottom)
perfectWindowRect.bottom = bestScreenRect.bottom;
// If the right edge is still falling off,
// save space for Finder’s disk icons as well.
if (perfectWindowRect.right > bestScreenRect.right)
{
perfectWindowRect.right = bestScreenRect.right;
// If we were on the main screen, leave room for Finder icons, too.
if (bestDevice == GetMainDevice())
perfectWindowRect.right -= kSpaceForFinderIcons;
}
}
}
// Stash our new rectangle inside of the Window’s dataHandle
// so that ZoomWindow does the right thing.
// (**((WStateDataHandle) (windowAsWindowPeek->dataHandle))).stdState = perfectWindowRect;
SetWindowStandardState ( fWindow, &perfectWindowRect );
}
// HEY YOU! Don’t forget to set the port to the window being zoomed
// Why, you ask? Because IM-IV-50 says to; otherwise you die
SetPortWindowPort ( fWindow );
Rect oldWindowRect = GetWindowPort ( fWindow )->portRect;
ZoomWindow(fWindow,zoomState,false);
Rect newWindowRect = GetWindowPort ( fWindow )->portRect;
this->AdjustForNewWindowSize(&oldWindowRect,&newWindowRect);
SetPort(oldPort);
}
void TWindow::ShowHide(Boolean showFlag)
{
// Here we need the “::” in front of ShowHide to indicate we are calling
// the global function, and not the method ShowHide. Unintended recursion
// can do bad things to the unsuspecting programmer.
// Some C++ programmers would always prepend the “::” on function calls.
::ShowHide(fWindow,showFlag);
fIsVisible = showFlag;
}
Boolean TWindow::EventFilter(EventRecord * /* theEvent */)
{
return false;
}
void TWindow::GetPerfectWindowSize(Rect *perfectSize)
{
*perfectSize = qd.screenBits.bounds;
}
void TWindow::GetWindowSizeLimits(Rect *limits)
{
limits->top = limits->left = kMinimumWindowSize;
limits->right = gDeskRectangle.right - gDeskRectangle.left;
limits->bottom = gDeskRectangle.bottom - gDeskRectangle.top;
}
void TWindow::AdjustForNewWindowSize(Rect * /* oldRect */, Rect * /* newSize */)
{
}
Boolean TWindow::IsVisible(void)
{
return fIsVisible;
}
Boolean TWindow::CanClose(Boolean /* quitting */)
{
return true;
}
Boolean TWindow::Close(void)
{
WindowRef newFrontWindow = nil;
if (FrontNonFloatingWindow() == fWindow)
newFrontWindow = GetNextWindow ( fWindow );
this->Activate(false);
if (fIsDialogWindow)
DisposeDialog((DialogRef) fWindow);
else
DisposeWindow(fWindow);
if (fWindowType == kModalWindow)
HiliteWindowsForModalDialog(true);
if (newFrontWindow)
HiliteAndActivateWindow(newFrontWindow,true);
return true;
}
Boolean TWindow::DeleteAfterClose(void)
{
return true;
}
void TWindow::AdjustMenusBeforeMenuSelection(void)
{
}
Boolean TWindow::DoMenuSelection(short /* menu */, short /* item */)
{
return false;
}
Boolean TWindow::DoCommand(CommandID theCommand)
{
if (theCommand == cClose)
{
if (this->CanClose(false) && this->Close() && this->DeleteAfterClose())
delete this;
return true;
}
return false;
}
void TWindow::ClickAndDrag(EventRecord * anEvent)
{
// By default, we just convert to local coordinates
// and call the window’s Click method.
GlobalToLocal(&anEvent->where);
this->Click(anEvent);
}
OSErr TWindow::HandleDrag(DragTrackingMessage dragMessage,DragReference theDrag)
{
OSErr result = dragNotAcceptedErr;
switch (dragMessage)
{
case dragTrackingEnterWindow:
result = this->DragEnterWindow(theDrag);
break;
case dragTrackingInWindow:
result = this->DragInWindow(theDrag);
break;
case dragTrackingLeaveWindow:
result = this->DragLeaveWindow(theDrag);
break;
default:
break;
}
return result;
}
OSErr TWindow::DragEnterWindow(DragReference /* theDrag */)
{
return dragNotAcceptedErr;
}
OSErr TWindow::DragInWindow(DragReference /* theDrag */)
{
return dragNotAcceptedErr;
}
OSErr TWindow::DragLeaveWindow(DragReference /* theDrag */)
{
return dragNotAcceptedErr;
}
OSErr TWindow::HandleDrop(DragReference /* theDrag */)
{
return dragNotAcceptedErr;
}
Boolean TWindow::IsPointInContentRgn( Point pt )
{
GetWindowContentRgn(fWindow, fgScratchRgn);
Boolean result = PtInRgn( pt, fgScratchRgn );
return result;
}
Boolean TWindow::IsMouseInContentRgn( DragReference dragRef )
{
Point globalMouse;
OSErr err;
err = GetDragMouse( dragRef, &globalMouse, 0L );
if ( err == noErr )
return( this->IsPointInContentRgn( globalMouse ) );
else
return( false );
}
Rect TWindow::GetContentsBounds(void)
{
Rect r;
GetWindowContentRgn(fWindow, fgScratchRgn);
r = (**fgScratchRgn).rgnBBox;
return r;
}
///////////////////////////////////////////////////////////////////////////
//
// Utility Functions used for floating windows
//
TWindow* GetWindowObject(WindowRef aWindow)
{
short wKind;
if (aWindow != nil)
{
wKind = GetWindowKind ( aWindow );
if (wKind >= userKind)
{
// All windowKinds >= userKind are based upon TWindow
return (TWindow *) GetWRefCon(aWindow);
}
}
return (TWindow *) nil;
}
////////////////////////////////////////////////////////////////////////
//
// Utility functions
pascal WindowRef
GetNewColorOrBlackAndWhiteWindow(short windowID, void *wStorage, WindowRef behind)
{
if (gHasColorQuickdraw)
return GetNewCWindow(windowID,wStorage,behind);
else
return GetNewWindow(windowID,wStorage,behind);
}
pascal WindowRef
NewColorOrBlackAndWhiteWindow(void *wStorage, const Rect *boundsRect, ConstStr255Param title, Boolean visible, short theProc, WindowRef behind, Boolean goAwayFlag, long refCon)
{
if (gHasColorQuickdraw)
return NewCWindow(wStorage,boundsRect,title,visible,theProc,behind,goAwayFlag,refCon);
else
return NewWindow(wStorage,boundsRect,title,visible,theProc,behind,goAwayFlag,refCon);
}
void DrawJustTheGrowIcon(WindowRef aWindow)
{
GrafPtr savedPort;
Rect growBoxRect;
GetPort(&savedPort);
SetPortWindowPort ( aWindow );
GetClip(TWindow::fgScratchRgn);
// clip to just the bottom right corner of the window
growBoxRect = GetWindowPort ( aWindow )->portRect;
growBoxRect.top = growBoxRect.bottom - kScrollbarWidth;
growBoxRect.left = growBoxRect.right - kScrollbarWidth;
ClipRect(&growBoxRect);
if (aWindow == FrontWindow())
DrawGrowIcon(aWindow);
else
{
InsetRect(&growBoxRect, 2, 2);
EraseRect(&growBoxRect);
}
SetClip(TWindow::fgScratchRgn);
SetPort(savedPort);
}
WindowRef LastFloatingWindow(void)
{
WindowRef aWindow = FrontWindow();
WindowRef lastFloater = (WindowRef) kNoFloatingWindows;
while ( aWindow != nil && GetWindowKind ( aWindow ) == kFloatingWindowKind )
{
if ( IsWindowVisible ( aWindow ))
lastFloater = (WindowRef) aWindow;
aWindow = GetNextWindow ( aWindow );
}
return lastFloater;
}
WindowRef FrontNonFloatingWindow(void)
{
WindowRef aWindow = (WindowRef) LMGetWindowList ();
// Skip over floating windows
while ( aWindow != nil && GetWindowKind ( aWindow ) == kFloatingWindowKind )
aWindow = GetNextWindow ( aWindow );
// Skip over invisible, but otherwise normal windows
while (aWindow != nil && !IsWindowVisible ( aWindow ))
aWindow = GetNextWindow ( aWindow );
return aWindow;
}
void HiliteAndActivateWindow(WindowRef aWindow,Boolean active)
{
GrafPtr oldPort;
TWindow * wobj = GetWindowObject(aWindow);
if (aWindow)
{
HiliteWindow(aWindow,active);
if (wobj != nil)
{
GetPort(&oldPort);
SetPortWindowPort ( aWindow );
wobj->Activate(active);
SetPort(oldPort);
}
}
}
void SuspendResumeWindows(Boolean resuming)
{
// When we suspend/resume, hide/show all the visible floaters
HiliteShowHideFloatingWindows(resuming,true);
}
void HiliteWindowsForModalDialog(Boolean hiliting)
{
// When we display a modal dialog, we need to unhighlight
// all visible floaters. We also need to re-hilite them
// afterwards.
HiliteShowHideFloatingWindows(hiliting,false);
}
void HiliteShowHideFloatingWindows(Boolean hiliting, Boolean dohiding)
{
WindowRef aWindow;
TWindow * wobj;
HiliteAndActivateWindow(FrontNonFloatingWindow(), hiliting);
aWindow = (WindowRef) LMGetWindowList();
while ( aWindow != nil && GetWindowKind ( aWindow ) == kFloatingWindowKind )
{
wobj = GetWindowObject ( aWindow );
// If we are hiding or showing, only hide/show windows
// that were visible to begin with.
// NOTE: We use our copy of the visible flag so we can
// automatically show floaters on a resume event.
// NOTE: Since this isn’t a method of TWindow, we don’t
// really need the “::” on ShowHide, but as long
// as we’re trying to avoid ambiguity.
if (dohiding && (wobj != nil) && (wobj->IsVisible()))
::ShowHide(aWindow,hiliting);
// All floaters are hilited if any floater is hilited
HiliteWindow( aWindow,hiliting);
aWindow = GetNextWindow ( aWindow );
}
}
///////////////////////////////////////////////////////////////////////////
//
// Routines used for dealing with windows and multiple screens
//
pascal void
CalculateWindowAreaOnDevice(short /* depth */,short /* deviceFlags */,GDHandle targetDevice,long userData)
{
CalcWindowAreaDeviceLoopUserData * deviceLoopDataPtr;
long windowAreaOnThisScreen;
Rect windowRectOnThisScreen;
deviceLoopDataPtr = (CalcWindowAreaDeviceLoopUserData *) userData;
SectRect(&deviceLoopDataPtr->fWindowBounds, &(**targetDevice).gdRect,&windowRectOnThisScreen);
OffsetRect(&windowRectOnThisScreen,-windowRectOnThisScreen.left,-windowRectOnThisScreen.top);
windowAreaOnThisScreen = windowRectOnThisScreen.right * windowRectOnThisScreen.bottom;
if (windowAreaOnThisScreen > deviceLoopDataPtr->fLargestArea)
{
deviceLoopDataPtr->fLargestArea = windowAreaOnThisScreen;
deviceLoopDataPtr->fScreenWithLargestPartOfWindow = targetDevice;
}
}
DeviceLoopDrawingUPP CallCalcWindowAreaOnDevice = NewDeviceLoopDrawingProc(&CalculateWindowAreaOnDevice);
void
FindScreenRectWithLargestPartOfWindow(WindowRef aWindow,Rect *theBestScreenRect,GDHandle * theBestDevice)
{
RgnHandle copyOfWindowStrucRgn;
CalcWindowAreaDeviceLoopUserData deviceLoopData;
// Use DeviceLoop to find out what GDevice contains the largest
// portion of the supplied window.
//
// NOTE: Assumes thePort == the Window Manager Port because we using
// the window strucRgn, not contRgn.
deviceLoopData.fScreenWithLargestPartOfWindow = nil;
deviceLoopData.fLargestArea = -1;
RgnHandle tempRgn = NewRgn ();
GetWindowContentRgn ( aWindow, tempRgn );
deviceLoopData.fWindowBounds = (**tempRgn).rgnBBox;
DisposeRgn ( tempRgn );
copyOfWindowStrucRgn = NewRgn();
GetWindowStructureRgn ( aWindow, copyOfWindowStrucRgn );
DeviceLoop(copyOfWindowStrucRgn,CallCalcWindowAreaOnDevice,(long) &deviceLoopData,singleDevices);
DisposeRgn(copyOfWindowStrucRgn);
*theBestDevice = deviceLoopData.fScreenWithLargestPartOfWindow;
*theBestScreenRect = (**(deviceLoopData.fScreenWithLargestPartOfWindow)).gdRect;
// Leave some space around the edges of the screen so window look good, AND
// if the best device is the main screen, leave space for the Menubar
InsetRect(theBestScreenRect,kScreenEdgeSlop,kScreenEdgeSlop);
if (GetMainDevice() == deviceLoopData.fScreenWithLargestPartOfWindow)
theBestScreenRect->top += GetMBarHeight();
}
///////////////////////////////////////////////////////////////////////////
//
// Drag Manager callback routines which dispatch to a window’s method
//
pascal OSErr
CallWindowDragTrackingHandler(DragTrackingMessage dragMessage,WindowRef theWindow,void * /* refCon */,DragReference theDrag)
{
TWindow *wobj = GetWindowObject(theWindow);
if (wobj)
return(wobj->HandleDrag(dragMessage,theDrag));
else
return dragNotAcceptedErr;
}
pascal OSErr
CallWindowDragReceiveHandler(WindowRef theWindow,void * /* refCon */,DragReference theDrag)
{
TWindow *wobj = GetWindowObject(theWindow);
if (wobj)
return(wobj->HandleDrop(theDrag));
else
return dragNotAcceptedErr;
}